﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;

namespace Xceed.Silverlight.DataGrid
{
  internal class DataContextInitializerVisitor : VisitorBase
  {
    public static double InitializationIncrementFactor = 0.3d;
    public static double InitialInitializationWeight = 15d;
    private static double MaximumInitializationWeight = 120d;
    private static double CellCreationWeight = 2d;
    private static double CellInitializationWeight = 1d;

    internal DataContextInitializerVisitor( DataGridControl datagrid, double maxInitializationWeight, bool reverseInitialization )
      :base(ChildrenPolicy.RenderedChildrenOnly, false)
    {
      m_datagrid = datagrid;
      m_maxInitializationWeight = Math.Min( maxInitializationWeight, DataContextInitializerVisitor.MaximumInitializationWeight );
      int columnCount = m_datagrid.DataGridPanel.AllColumns.Count();
      m_totalCellCreationWeight = ( DataContextInitializerVisitor.CellCreationWeight * columnCount );
      m_totalCellInitializationWeight = ( DataContextInitializerVisitor.CellInitializationWeight * columnCount );
      m_reverseInitialization = reverseInitialization;
    }


    public bool InitializationOccured
    {
      get
      {
        return ( m_contextInitializedCount != 0 );
      }
    }

    public bool NeedMoreInitialization
    {
      get
      {
        return m_needMoreInitialization;
      }
    }

    public override void Visit( DataRow dataRow )
    {
      WrapperBase parentWrapper = ( WrapperBase )dataRow.Parent;

      if( this.RequestInitializationAccess() )
      {
        if( m_datagrid.InitializeCells( dataRow ) )
        {
          m_contextInitializedCount += m_totalCellCreationWeight;
        }

        if( this.RequestInitializationAccess() )
        {
          if( m_datagrid.UpdateElementInternal( dataRow, true ) )
          {
            m_contextInitializedCount += m_totalCellInitializationWeight;
          }
        }
      }
    }

    public override void Visit( VirtualContainerBase containerBase )
    {
      IEnumerable<ILayoutElement> elements = (m_reverseInitialization)
                               ? containerBase.RenderedElements.Reverse()
                               : containerBase.RenderedElements;

      if( elements != null )
      {
        foreach( ILayoutElement elem in elements )
        {
          if( this.IsStopped )
            break;

          ( ( IVisitorElement )elem ).Accept( this );
        }
      }
    }

    private bool RequestInitializationAccess()
    {
      if( m_maxInitializationWeight > m_contextInitializedCount )
      {
        return true;
      }
      else
      {
        m_needMoreInitialization = true;
        this.StopVisit();
        return false;
      }
    }

    private bool m_reverseInitialization;
    private double m_contextInitializedCount; //0
    private bool m_needMoreInitialization; //false
    private DataGridControl m_datagrid;
    private double m_maxInitializationWeight;
    private double m_totalCellCreationWeight;
    private double m_totalCellInitializationWeight;
  }
}
